package org.dromara.iot.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.iot.domain.IotElevator;
import org.dromara.iot.domain.IotElevatorTiring;
import org.dromara.iot.domain.bo.IotElevatorTiringBo;
import org.dromara.iot.domain.bo.IotRescueRecordBo;
import org.dromara.iot.domain.vo.IotElevatorTiringVo;
import org.dromara.iot.domain.vo.IotElevatorVo;
import org.dromara.iot.domain.vo.IotRescueRecordVo;
import org.dromara.iot.enums.BusinessCodeEnum;
import org.dromara.iot.enums.TiringStateEnum;
import org.dromara.iot.mapper.IotElevatorTiringMapper;
import org.dromara.iot.service.IIotElevatorService;
import org.dromara.iot.service.IIotElevatorTiringService;
import org.dromara.iot.service.IIotRescueRecordService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 电梯困人管理Service业务层处理
 *
 * @author lsl
 * @date 2024-06-23
 */
@RequiredArgsConstructor
@Service
public class IotElevatorTiringServiceImpl implements IIotElevatorTiringService {

    private final IotElevatorTiringMapper baseMapper;

    private final IIotElevatorService elevatorInfoService;

    private final IIotRescueRecordService rescueRecordService;

    private final UserService userService;

    /**
     * 查询电梯困人管理
     */
    @Override
    public IotElevatorTiringVo queryById(Long tiringId) {
        IotElevatorTiringVo iotElevatorTiringVo = baseMapper.selectVoById(tiringId);
        List<IotRescueRecordVo> rescueRecordVos = rescueRecordService.queryListByTiringId(tiringId);
        iotElevatorTiringVo.setRescueRecordList(rescueRecordVos);
        iotElevatorTiringVo.setRescueUserAvatar(userService.selectAvatarById(iotElevatorTiringVo.getRescueUserId()));
        String datePoor = DateUtils.getDatePoor(DateUtil.date(), iotElevatorTiringVo.getReportTime());
        iotElevatorTiringVo.setTiringDuration(datePoor);
        return iotElevatorTiringVo;
    }

    /**
     * 查询电梯困人管理列表
     */
    @Override
    public TableDataInfo<IotElevatorTiringVo> queryPageList(IotElevatorTiringBo bo, PageQuery pageQuery) {
        QueryWrapper<IotElevator> lqw = Wrappers.query();
        Page<IotElevatorTiringVo> result = baseMapper.selectOwnVoPage(pageQuery.build(), lqw);
        for (IotElevatorTiringVo tiring : result.getRecords()) {
            if (StringUtils.isNotBlank(tiring.getTiringDuration())) {
                continue;
            }
            String datePoor = DateUtils.getDatePoor(DateUtil.date(), tiring.getReportTime());
            tiring.setTiringDuration(datePoor);
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询电梯困人管理列表
     */
    @Override
    public List<IotElevatorTiringVo> queryList(IotElevatorTiringBo bo) {
        LambdaQueryWrapper<IotElevatorTiring> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IotElevatorTiring> buildQueryWrapper(IotElevatorTiringBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IotElevatorTiring> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getElevatorId() != null, IotElevatorTiring::getElevatorId, bo.getElevatorId());
        lqw.like(StringUtils.isNotBlank(bo.getElevatorName()), IotElevatorTiring::getElevatorName, bo.getElevatorName());
        lqw.eq(StringUtils.isNotBlank(bo.getReportMan()), IotElevatorTiring::getReportMan, bo.getReportMan());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringCode()), IotElevatorTiring::getTiringCode, bo.getTiringCode());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringFloor()), IotElevatorTiring::getTiringFloor, bo.getTiringFloor());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringType()), IotElevatorTiring::getTiringType, bo.getTiringType());
        lqw.eq(bo.getReportTime() != null, IotElevatorTiring::getReportTime, bo.getReportTime());
        lqw.eq(bo.getRescueTime() != null, IotElevatorTiring::getRescueTime, bo.getRescueTime());
        lqw.eq(bo.getCompleteTime() != null, IotElevatorTiring::getCompleteTime, bo.getCompleteTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringDuration()), IotElevatorTiring::getTiringDuration, bo.getTiringDuration());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringState()), IotElevatorTiring::getTiringState, bo.getTiringState());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringCause()), IotElevatorTiring::getTiringCause, bo.getTiringCause());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitudeStart()), IotElevatorTiring::getLongitudeStart, bo.getLongitudeStart());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitudeStart()), IotElevatorTiring::getLatitudeStart, bo.getLatitudeStart());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitudeEnd()), IotElevatorTiring::getLongitudeEnd, bo.getLongitudeEnd());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitudeEnd()), IotElevatorTiring::getLatitudeEnd, bo.getLatitudeEnd());
        lqw.eq(bo.getRescueUserId() != null, IotElevatorTiring::getRescueUserId, bo.getRescueUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getRescuePeople()), IotElevatorTiring::getRescuePeople, bo.getRescuePeople());
        lqw.eq(StringUtils.isNotBlank(bo.getRescuePeopleSign()), IotElevatorTiring::getRescuePeopleSign, bo.getRescuePeopleSign());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmPeople()), IotElevatorTiring::getConfirmPeople, bo.getConfirmPeople());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmPeopleSign()), IotElevatorTiring::getConfirmPeopleSign, bo.getConfirmPeopleSign());
        lqw.eq(StringUtils.isNotBlank(bo.getTiringDescribe()), IotElevatorTiring::getTiringDescribe, bo.getTiringDescribe());
        lqw.eq(StringUtils.isNotBlank(bo.getIsApproved()), IotElevatorTiring::getIsApproved, bo.getIsApproved());
        lqw.eq(StringUtils.isNotBlank(bo.getRescueSign()), IotElevatorTiring::getRescueSign, bo.getRescueSign());
        return lqw;
    }

    /**
     * 新增电梯困人管理
     */
    @Override
    public Boolean insertByBo(IotElevatorTiringBo bo) {
        IotElevatorTiring add = MapstructUtils.convert(bo, IotElevatorTiring.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setTiringId(add.getTiringId());
        }
        return flag;
    }

    /**
     * 修改电梯困人管理
     */
    @Override
    public Boolean updateByBo(IotElevatorTiringBo bo) {
        IotElevatorTiring update = MapstructUtils.convert(bo, IotElevatorTiring.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IotElevatorTiring entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除电梯困人管理
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 查询当前困人
     */
    @Override
    public IotElevatorTiringVo selectCurrentTiringByElevatorId(Long elevatorId) {
        LambdaQueryWrapper<IotElevatorTiring> lqw = Wrappers.lambdaQuery();
        lqw.eq(IotElevatorTiring::getElevatorId, elevatorId);
        lqw.ne(IotElevatorTiring::getTiringState, TiringStateEnum.CONFIRM.getCode());
        return baseMapper.selectVoOne(lqw);
    }

    /**
     * 上报电梯困人
     */
    @Override
    public int reportTiring(IotElevatorTiringBo bo) {
        //避免电梯同时上报问题
        IotElevatorTiringVo iotElevatorTiringVo = this.selectCurrentTiringByElevatorId(bo.getElevatorId());
        if (ObjectUtil.isNotNull(iotElevatorTiringVo)) {
            throw new ServiceException("电梯已经上报困人，请勿重复上报");
        }
        IotElevatorVo iotElevatorVo = elevatorInfoService.queryById(bo.getElevatorId());
        if (iotElevatorVo == null) {
            throw new ServiceException("电梯不存在");
        }
        //电梯名称
        bo.setElevatorName(iotElevatorVo.getElevatorName());
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setReportMan(loginUser.getNickname());
        //困人单号
        bo.setTiringCode(BusinessCodeEnum.TIRING.getBusinessCode());
        //困人类型(0:人工上报;1:非平层停靠困人;2:不开门困人)
        bo.setTiringType("0");
        //上报时间
        bo.setReportTime(DateUtil.date());
        //状态（0:上报困人;1:启动救援;2:接受任务;3:到达现场;4:完成救援;5:确认完成）
        bo.setTiringState(TiringStateEnum.REPORT.getCode());
        this.insertByBo(bo);
        //上报困人记录
        IotRescueRecordBo rescueRecord = new IotRescueRecordBo();
        rescueRecord.setTiringId(bo.getTiringId());
        rescueRecord.setTiringState(TiringStateEnum.REPORT.getCode());
        Boolean flag = rescueRecordService.insertByBo(rescueRecord);
        if (flag) {
            WebSocketUtils.publishAll(bo.getElevatorName() + "困人了！");
        }
        return flag ? 1 : 0;
    }

    /**
     * 开始救援
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean starRescue(IotElevatorTiringBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorTiringVo elevatorTiring = this.queryById(bo.getTiringId());
        if (elevatorTiring == null) {
            throw new ServiceException("困人信息不存在");
        }
        if (elevatorTiring.getRescueUserId() != null) {
            if (!elevatorTiring.getRescueUserId().equals(loginUser.getUserId())) {
                throw new ServiceException("已经有人正在进行救援任务");
            } else {
                return true;
            }
        }
        //启动救援
        IotRescueRecordBo rescueRecord = new IotRescueRecordBo();
        rescueRecord.setUserId(loginUser.getUserId());
        rescueRecord.setTiringId(bo.getTiringId());
        rescueRecord.setTiringState(TiringStateEnum.RESCUE.getCode());
        rescueRecordService.insertByBo(rescueRecord);
        //接收任务
        rescueRecord.setTiringState(TiringStateEnum.ACCEPT.getCode());
        rescueRecord.setCreateTime(DateUtil.date());
        rescueRecord.setRemark(loginUser.getNickname() + " 已接受救援任务");
        rescueRecord.setRecordId(null);
        rescueRecordService.insertByBo(rescueRecord);
        bo.setTiringState(TiringStateEnum.ACCEPT.getCode());
        bo.setLongitudeStart(bo.getLongitudeStart());
        bo.setLatitudeStart(bo.getLatitudeStart());
        bo.setRescuePeople(loginUser.getNickname());
//        elevatorTiring.setRescueSign("0");

        bo.setRescueUserId(loginUser.getUserId());
        bo.setRescueTime(DateUtil.date());
        return this.updateByBo(bo);
    }

    /**
     * 救援签到
     */
    @Override
    public Boolean rescueSign(IotElevatorTiringBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorTiringVo elevatorTiring = this.queryById(bo.getTiringId());
        if (elevatorTiring == null) {
            throw new ServiceException("困人信息不存在");
        }
        if (elevatorTiring.getRescueUserId() == null) {
            throw new ServiceException("任务没有被接收");
        }
        if (!elevatorTiring.getRescueUserId().equals(loginUser.getUserId())) {
            throw new ServiceException("已经有人正在进行救援任务");
        }
        if (elevatorTiring.getRescueSign().equals("0")) {
            bo.setRescueSign("1");
            bo.setTiringState(TiringStateEnum.ARRIVE.getCode());
            this.updateByBo(bo);
            //到达现场
            IotRescueRecordBo rescueRecord = new IotRescueRecordBo();
            rescueRecord.setUserId(loginUser.getUserId());
            rescueRecord.setTiringId(bo.getTiringId());
            rescueRecord.setTiringState(TiringStateEnum.ARRIVE.getCode());
            rescueRecord.setRemark(loginUser.getNickname() + " 已赶往救援现场");
            rescueRecordService.insertByBo(rescueRecord);
        }
        return true;
    }

    /**
     * 救援完成
     */
    @Override
    public Boolean rescueComplete(IotElevatorTiringBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorTiringVo elevatorTiring = this.queryById(bo.getTiringId());
        if (elevatorTiring == null) {
            throw new ServiceException("困人信息不存在");
        }
        if (elevatorTiring.getRescueUserId() == null) {
            throw new ServiceException("任务没有被接收");
        }
        if (!elevatorTiring.getRescueUserId().equals(loginUser.getUserId())) {
            throw new ServiceException("已经有人正在进行救援任务");
        }
        bo.setCompleteTime(DateUtil.date());
        bo.setTiringState(TiringStateEnum.COMPLETE.getCode());
        bo.setTiringDuration(DateUtils.getDatePoor(DateUtil.date(), elevatorTiring.getReportTime()));
        this.updateByBo(bo);
        //完成救援111
        IotRescueRecordBo rescueRecord = new IotRescueRecordBo();
        rescueRecord.setUserId(loginUser.getUserId());
        rescueRecord.setTiringId(bo.getTiringId());
        rescueRecord.setTiringState(TiringStateEnum.COMPLETE.getCode());
        rescueRecord.setRemark(loginUser.getNickname() + " 已成功解救");
        rescueRecordService.insertByBo(rescueRecord);
        return true;
    }

    /**
     * 确认救援完成
     */
    @Override
    public Boolean confirmComplete(IotElevatorTiringBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        IotElevatorTiringVo elevatorTiring = this.queryById(bo.getTiringId());
        if (elevatorTiring == null) {
            throw new ServiceException("困人信息不存在");
        }
        if (!elevatorTiring.getTiringState().equals(TiringStateEnum.COMPLETE.getCode())) {
            throw new ServiceException("救援任务未完成");
        }
        //@TODO 判断是否为维修经理
//        if (!userRoles.contains(BusinessConstants.KEEP_MANAGER)) {
//            return error(Constants.UNVERIFY, "该用户不是维保经理");
//        }
        bo.setConfirmPeople(loginUser.getNickname());
        bo.setTiringState(TiringStateEnum.CONFIRM.getCode());
        this.updateByBo(bo);
        //确认完成
        IotRescueRecordBo rescueRecord = new IotRescueRecordBo();
        rescueRecord.setUserId(loginUser.getUserId());
        rescueRecord.setTiringId(bo.getTiringId());
        rescueRecord.setTiringState(TiringStateEnum.CONFIRM.getCode());
        rescueRecord.setRemark(loginUser.getNickname() + " 确认救援任务已完成");
        rescueRecordService.insertByBo(rescueRecord);
        return true;
    }
}
